
#include <BEvent>
#include <BKeyEvent>
#include <BMouseEvent>
#include <BFocusEvent>

#include <BCamera>
#include <BViewer>
#include <BStrollHandler>
#include "member_BStrollHandler.h"

using namespace BWE;

#define member					(*(member_BStrollHandler*)_ptr)
#define member_allocate()		_ptr = new member_BStrollHandler(this)
#define member_release()		delete (member_BStrollHandler*)_ptr

BStrollHandler::BStrollHandler()
{
	member_allocate();
}
BStrollHandler::~BStrollHandler()
{
	member_release();
}

void BStrollHandler::setMoveStep(float moveStep)
{
	member.moveSpeed = moveStep;
}
float BStrollHandler::moveStep() const
{
	return member.moveSpeed;
}

void BStrollHandler::setRotateStep(float rotateStep)
{
	member.rotateStep = rotateStep;
}
float BStrollHandler::rotateStep() const
{
	return member.rotateStep;
}

void BStrollHandler::paint(BPainter& painter)
{

}
void BStrollHandler::render(BRender& render)
{

}

void BStrollHandler::event(BEvent& event)
{
	double time = event.time();

	BCamera* camera = this->camera();
	if (!camera)
		return;

	BVector position = camera->position();
	BVector direct = camera->center() - position;
	direct.normalize();

	BVector up = camera->up();
	up.normalize();

	BVector right = direct.cross(up);
	right.normalize();

	up = right.cross(direct);
	up.normalize();

	float timeDif = time - member.time;
	float movement = (time - member.time) * member.moveSpeed;
	member.time = time;

	BVector move;
	if (member.wDown)		move += direct * member.moveSpeed;
	if (member.sDown)		move -= direct * member.moveSpeed;
	if (member.aDown)		move -= right * member.moveSpeed;
	if (member.dDown)		move += right * member.moveSpeed;
	if (member.qDown)		move += up * member.moveSpeed;
	if (member.zDown)		move -= up * member.moveSpeed;

	if (move != BVector())
	{
		const BVector& position = camera->position();
		const BVector& center = camera->center();
		camera->setPosition(position + move);
		camera->setCenter(center + move);
		this->fresh();
	}
}

bool BStrollHandler::keyUpEvent(const BKeyEvent& keyEvent)
{
	member.time = keyEvent.time();
	Key key = keyEvent.key();

	if(key == Key_W)		member.wDown = false;
	if(key == Key_S)		member.sDown = false;
	if(key == Key_A)		member.aDown = false;
	if(key == Key_D)		member.dDown = false;
	if(key == Key_Q)		member.qDown = false;
	if(key == Key_Z)		member.zDown = false;

	return true;
}
bool BStrollHandler::keyDownEvent(const BKeyEvent& keyEvent)
{
	Key key = keyEvent.key();

	if(key == Key_W)		member.wDown = true;
	if(key == Key_S)		member.sDown = true;
	if(key == Key_A)		member.aDown = true;
	if(key == Key_D)		member.dDown = true;
	if(key == Key_Q)		member.qDown = true;
	if(key == Key_Z)		member.zDown = true;

	return true;
}

bool BStrollHandler::mouseEnterEvent(const BMouseEvent& mouseEvent)
{
	member.wDown = false;
	member.sDown = false;
	member.aDown = false;
	member.dDown = false;
	member.qDown = false;
	member.zDown = false;
	member.rightDown = false;
	return false;
}
bool BStrollHandler::mouseLeaveEvent(const BMouseEvent& mouseEvent)
{
	member.wDown = false;
	member.sDown = false;
	member.aDown = false;
	member.dDown = false;
	member.qDown = false;
	member.zDown = false;
	member.rightDown = false;
	return false;
}

bool BStrollHandler::mousePressEvent(const BMouseEvent& mouseEvent)
{
	Button button = mouseEvent.button();
	BPoint pos = mouseEvent.pos();

	if(button == Button_Right)
	{
		member.rightDown = true;
		member.rightDownPos = pos;
	}
	if(button == Button_Middle)
	{
		member.middleDown = true;
	}
	return false;
}
bool BStrollHandler::mouseReleaseEvent(const BMouseEvent& mouseEvent)
{
	Button button = mouseEvent.button();
	BPoint pos = mouseEvent.pos();

	if(button == Button_Right)
	{
		member.rightDown = false;
	}
	if(button == Button_Middle)
	{
		member.middleDown = false;
	}
	return false;
}
bool BStrollHandler::mouseMoveEvent(const BMouseEvent& mouseEvent)
{
	Button button = mouseEvent.button();
	BPoint pos = mouseEvent.pos();

	if (!member.rightDown)
		return false;

	BPoint p0 = member.rightDownPos;
	BPoint p1 = pos;
	if (p0 == p1)
		return false;

	BViewer* viewer = this->viewer();
	BCamera* camera = viewer->camera();
	BVector position = camera->position();
	BVector center = camera->center();
	BVector up = camera->up();
	BVector direct = center - position;
	direct.normalize();
	BVector right = direct.cross(up);
	right.normalize();

	if (p1.y() != p0.y())
	{
		float angelV = (p1.y() - p0.y()) / 180.0f * PI;
		BQuater quaterV(angelV * 0.3f, right);
		direct *= quaterV;
	}
	if (p1.x() != p0.x())
	{
		float angleH = (p1.x() - p0.x()) / 180.0f * PI;
		BQuater quaterH(angleH * 0.3f, up);
		direct *= quaterH;
	}
	direct.setLength((center - position).length());

	camera->setCenter(position + direct);
	member.rightDownPos = pos;
	this->fresh();
	return true;
}
bool BStrollHandler::mouseWheelEvent(const BMouseEvent& mouseEvent)
{
	BViewer* viewer = this->viewer();
	BCamera* camera = viewer->camera();
	BVector position = camera->position();
	BVector direct = camera->center() - position;
	direct.normalize();
	BVector offset = direct * member.moveSpeed * -mouseEvent.wheel();
	camera->setPosition(position + offset);
	this->fresh();
	return true;
}


